/**
 * @公司:公约树
 * @位置:苏州
 * @Classname AnimeProperty
 * @Date 2022-05-30 下午 11:17
 * @Created by hanWanLu
 * @auther 中文:韩万路
 */


package com.animeJava.mode.animeModel;

import com.animeJava.core.EasingData;
import com.animeJava.dao.animeEvent.AnimeEventFinal;
import com.animeJava.dao.animeEvent.AnimeRender;
import com.animeJava.enumData.DirectionEnum;
import com.animeJava.enumData.EasingDataEnum;
import com.animeJava.mode.AnimeModel;
import com.animeJava.mode.AnimeRunStart;
import com.animeJava.mode.KeyModel;
import com.animeJava.mode.KeyPlayRank;
import com.animeJava.util.AnimeException;

import java.util.*;

/**
 * 动画初始设置的值
 */
public class AnimeProperty extends AnimeModel {
    private List<KeyModel>  keyFrames       =   new ArrayList<KeyModel>();  //关键帧
    private long            duration    =   1000;	 //持续时间 单位毫秒	number, function (el, index, total)
    private EasingData      easing      =   EasingDataEnum.EASE_IN_OUT.getData();  //easing	'easeOutElastic'	console log anime.easings to get the complete functions list
    private AnimeRender     update;                 //动画渲染中


    public AnimeProperty() {
    }
    public AnimeProperty(HashMap<String , Object> params) {
        super(params);
        if(params != null){
            Set<Map.Entry<String, Object>> entries = params.entrySet();
            for (Map.Entry<String, Object> map: entries) {
                if("easing".equals(map.getKey()) && map.getValue() != null){
                    this.easing = (EasingData) map.getValue();
                    break;
                }
                if("duration".equals(map.getKey()) && map.getValue() != null){
                    this.duration = (long) map.getValue();
                }
                if("update".equals(map.getKey()) && map.getValue() != null){
                    this.update = (AnimeRender) map.getValue();
                }
            }
        }
    }
    public AnimeProperty(long delay, long duration, boolean autoplay, boolean loop, DirectionEnum direction, EasingData easing, AnimeEventFinal begin, AnimeRender update, AnimeEventFinal complete) {
        super(delay,autoplay,loop,direction,begin,complete);

        this.duration = duration;
        this.easing = easing;
        this.update = update;

    }


    @Override
    public long animeFactory(long animeKey , int FPS , AnimeRunStart animeRunStart, AnimeEventFinal begin, AnimeRender update, AnimeEventFinal complete) throws AnimeException {

        //是多少次才可开始执行动画
        long delayFrequency = this.getDelay() / FPS;
        //当前动画有多少次的执行中时间
        long durationFrequency = this.getDuration() / FPS;
        //获取当前的帧数大于延时的时间后的帧数;
        double k = (animeKey - delayFrequency);
        //获取当前是否是来回的状态
        DirectionEnum direction = this.getDirection();
        //获取当前动画执行到了百分之几了
        double thisPath = 0;
        switch (direction){
            case NORMAL:{   //正常
                thisPath = k / durationFrequency;
                break;
            }
            case REVERSE:{  //倒叙
                thisPath = 1 - (k / durationFrequency );
                break;
            }
            case ALTERNATE:{    //来回
                thisPath = (k / durationFrequency >= 0.5? 0.5 - (k / durationFrequency - 0.5):k / durationFrequency )*2;
                break;
            }
        }
        //插入当前时间的百分比
        animeRunStart.setPathPercentage(thisPath);

        //********************动画延时后开始执行****************************//
        //如果当前是延时后的动画 并且动画还未开始
        if(animeKey > delayFrequency && animeRunStart.getRunStart() == 0){
            animeRunStart.setRunStart(1);
            //动画开始执行
            if(this.getBegin() != null){
                //如果run报错则清空当前的动画
                this.getBegin().run("");
            }
            if(begin != null)begin.run("动画开始执行");
        }
        //********************动画延时后执行中****************************//
        //当前的帧数大于延时的时间  并且 小于 延时时间加上 总共时间数 并且动画是在开始之中
        if(animeKey >= delayFrequency && animeKey <= delayFrequency+ durationFrequency && animeKey != 0  ){
            //当下获取贝塞尔曲线的图
            EasingData easing = this.getEasing();
            //动画中执行

            //如果run报错则清空当前的动画
//                            Map<Double, Double[]> keyFrames = this.getKeyFrames();
            List<KeyModel> keyFrames = this.getKeyFrames();

            //动画列队计算
            Map<Integer, KeyPlayRank> keyPlayRankS = new HashMap<>();

            //当前动画的百分之几 到
            //解析所有帧数列表中的单个帧数据  筛选数据
            for (int i = 0; i < keyFrames.size(); i++) {
                KeyModel keyFramesItem = keyFrames.get(i);

                Double keyNameItem = keyFramesItem.getKey();
                Double[] doublesDataList = keyFramesItem.getKeyData();



                for (int j = 0; j < doublesDataList.length; j++) {
                    //获取每一帧的in和to
                    Double aDouble = doublesDataList[j];

                    if(keyPlayRankS.get(j) == null){
                        KeyPlayRank keyPlayRankNew = new KeyPlayRank();
                        keyPlayRankS.put(j ,keyPlayRankNew );
                        keyPlayRankNew.setThisDataIndex(j);
                    }
                    if(aDouble != null  ){


                        KeyPlayRank keyPlayRank = keyPlayRankS.get(j);
                        //如果当前是在当前的帧数之前则不添加

                        if( keyPlayRank.getInData() == null){   //如果in 是空的则执行当前
                            keyPlayRank.setInData( doublesDataList[j]);
                            keyPlayRank.setStartTime( keyNameItem);
                        }else if( keyPlayRank.getToData() == null){ //如果 in 不为空  to为空则执行里面
                            //如果当前to的帧动画定义的时间 小于 当前时间线的百分比  则给to的帧动画换成 in的帧动画
                            keyPlayRank.setToData( doublesDataList[j]);
                            keyPlayRank.setEndTime( keyNameItem);
                        }else if( aDouble != null) {    //如果in 不为空 和 to不为空则 则判断一下这一帧是否有数据如果有数据则给这一帧的数据往前推进一下

                            Double toData = keyPlayRank.getToData();
                            Double endTime = keyPlayRank.getEndTime();
                            keyPlayRank.setInData(toData );
                            keyPlayRank.setStartTime(endTime);

                            keyPlayRank.setToData( doublesDataList[j]);
                            keyPlayRank.setEndTime( keyNameItem);

                        }
                    }
                }

            }
            //解析筛选数据
            Set<Integer> integers = keyPlayRankS.keySet();
            List<Double> runData = new ArrayList<Double>(integers.size());    //执行解析后的数据
            //开辟空内存
            for (Integer keyCode: integers) {
                runData.add(null);
            }

            for (Integer keyCode: integers) {
                KeyPlayRank keyPlayRank = keyPlayRankS.get(keyCode);
                runData.set(keyCode , keyPlayRank.computedThisData(easing,thisPath) );
            }

            //赋值执行
            if(this.getUpdate() != null &&  runData != null && keyPlayRankS.keySet().size() != 0 ){
                this.getUpdate().run(thisPath,null,runData);
            }
            if(update != null &&  runData != null && keyPlayRankS.keySet().size() != 0 )update.run(thisPath,null,runData);
        }

        //********************动画走完执行****************************//
        //判断当前的时间是否走完  如果走完  则判断是  否循环
        if(animeKey > delayFrequency+durationFrequency +1  && animeRunStart.getRunStart() != -1){

            animeRunStart.setRunStart(-1); //标记-1

            //动画完执行
            if(this.getComplete() != null){
                //如果run报错则清空当前的动画
                this.getComplete().run("动画执行完毕");
            }
            if(complete != null)complete.run("动画执行完毕");
            //并且判断是否循环
            if(this.isLoop()){
                animeKey = 0; //从新执行了
                animeRunStart.setRunStart(0); //标记 0 开始
            }
        }else{
            //每一帧的执行
            //这里控制动画的百分比
            //没走完接着走
            if(animeRunStart.getRunStart() != -1){
                animeKey++;
            }
            //判断当前是否是自动播放如果是自动播放则自动修改为0
            if(animeRunStart.getRunStart() == -1){
                if(this.isLoop()){
                    animeRunStart.setRunStart(0);
                }
                //是手动控制并且不是循环则执行当前
                if(!this.isLoop()){
                    animeKey = (long) ((delayFrequency+durationFrequency)*animeRunStart.getAnimeKeyV2());
                }
            }
        }
        return animeKey;

    }

    public List<KeyModel> getKeyFrames() {
        return keyFrames;
    }

    /**
     * 添加帧数 <a href="http://www.baidu.com">重要</a>
     * @param keyPosition   添加帧数比 0~100
     * @param keyFrames     创建每帧位置 可以为空
     */
    @Deprecated
    public void addKeyFrames(int keyPosition ,Double ... keyFrames) {
        if(keyPosition >= 0 && keyPosition <=100){
            this.keyFrames.add(new KeyModel((double) (keyPosition/100),keyFrames));
        }else{
            new Exception("不可在范围之外0~100");
        }

    }
    /**
     * 添加帧数 <a href="http://www.baidu.com">重要</a>
     * @param keyPosition   添加帧数比 0~1
     * @param keyFrames     创建每帧位置 可以为空
     */
    public void addKeyFrames(double keyPosition ,Double ... keyFrames) {
        if(keyPosition >= 0 && keyPosition <=1){
            this.keyFrames.add(new KeyModel((double) (keyPosition),keyFrames));
        }else{
            new Exception("不可在范围之外0~1");
        }

    }
    public EasingData getEasing() {
        return easing;
    }

    public void setEasing(EasingData easing) {
        this.easing = easing;
    }

    public long getDuration() {
        return duration;
    }

    public void setDuration(long duration) {
        this.duration = duration;
    }

    public AnimeRender getUpdate() {
        return update;
    }

    @Deprecated
    public void setUpdate(AnimeRender update) {
        this.update = update;
    }
}
